#include "decoder.h"
#include <iostream>
using namespace std;
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
}

namespace lcf
{

    bool Decoder::Send(const AVPacket *pkt) // 发送解码
    {
        unique_lock<mutex> lock(mtx_);
        if (!context_)
            return false;
        auto re = avcodec_send_packet(context_, pkt);
        if (re != 0)
            return false;
        return true;
    }

    bool Decoder::Recv(AVFrame *frame) // 获取解码
    {
        unique_lock<mutex> lock(mtx_);
        if (!context_)
            return false;
        auto f = frame;
        if (context_->hw_device_ctx) // 硬件加速
        {
            f = av_frame_alloc();
        }
        auto re = avcodec_receive_frame(context_, f);
        if (re == 0)
        {
            if (context_->hw_device_ctx) // GPU解码
            {
                // 显存转内存 GPU =》 CPU
                re = av_hwframe_transfer_data(frame, f, 0);
                av_frame_free(&f);
                if (re != 0)
                {
                    PrintErr(re);
                    return false;
                }
            }
            return true;
        }
        if (context_->hw_device_ctx)
            av_frame_free(&f);
        return false;
    }

    bool Decoder::Decode(AVPacket *srcPacket, AVFrame *dstFrame)
    {
        if (!srcPacket || !dstFrame)
            return false;
        std::unique_lock<std::mutex> lock(mtx_);
        if (!context_)
            return false;
        // 发送到解码线程
        int sendRes = avcodec_send_packet(context_, srcPacket);
        if (sendRes != 0)
        {
            PrintErr(sendRes);
            return false;
        }
        // 接收解码线程数据
        bool recvRes = avcodec_receive_frame(context_, dstFrame);
        if (recvRes != 0)
        {
            PrintErr(recvRes);
            return false;
        }
        return true;
    }
}
